#pragma once

#include<iostream>
#include<queue>
#include<pthread.h>

static const int gmaxcap=5;

template <class T>
class BlockQueue
{
public:
    BlockQueue(const int& maxcap=gmaxcap):_maxcap(maxcap)
    {
        pthread_mutex_init(&_mutex,nullptr);
        pthread_cond_init(&_pcond,nullptr);
        pthread_cond_init(&_ccond,nullptr);

    }

    void push(const T& in)//输入型参数，const &
    {
        pthread_mutex_lock(&_mutex);
        //1.判断
        while(is_full())
        {
            pthread_cond_wait(&_pcond,&_mutex);//满了不能生产，需要等待
        }
        //2.一定没有满
        _q.push(in); 
        //3.绝对能保证阻塞队列有数据
        pthread_cond_signal(&_ccond);
        pthread_mutex_unlock(&_mutex);
    }

    void pop(T* out)//输出型参数，*，//输入输出型，&
    {
        pthread_mutex_lock(&_mutex);
        //1.判断
        while(is_empty())
        {
            pthread_cond_wait(&_ccond,&_mutex);
        }
        //2.一定不为空
        *out=_q.front();
        _q.pop();
        //3.绝对能保证阻塞队列有一个空位置
        pthread_cond_signal(&_pcond);
        pthread_mutex_unlock(&_mutex);
    }

    ~BlockQueue()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_pcond);
        pthread_cond_destroy(&_ccond);
    }
private:
    bool is_empty()
    {
        return _q.empty();
    }
    bool is_full()
    {
        return _q.size()==_maxcap;
    }
private:
    std::queue<T> _q;
    int _maxcap;//队列上限
    pthread_mutex_t _mutex;
    pthread_cond_t _pcond;//生产者对应的条件变量
    pthread_cond_t _ccond;//消费者对应的条件变量
};
